#ifndef _SLOT1_H
#define _SLOT1_H

#include "DynamicQObject.h"
#import <objc/Object.h>
#import <objc/objc-api.h>
#import <objc/encoding.h>

#define Slot0 Slot
#define OBJC_SLOT(qty, selector, ...)   \
           new Slot##qty __VA_ARGS__(selector)


/**
 * Encapsula los slots para el objeto DynamicSlot.
 * Éste objeto llama al método del objeto objective C con sus repectivos
 * parámetros, cada uno hace un cast al tipo correspondiente
 */


/**
 * Slot sin parámetros
 */
class Slot : public VirtualSlot
{
public:
    Slot(SEL selector) : VirtualSlot(selector){};

    void call(QObject *sender, void **arguments)
    {
        this->imp(this->target, this->sel);
    }
};

/**
 * Macro que crea la variable _v del tipo _t *, haciendo un cast del
 * último argumento _a. 
 * Se usa para los diferentes Slot, para hacer un cast más generico
 */
#define cast_ptr(_t, _v, _a) _t *_v = reinterpret_cast<_t(*)>(_a)

/**
 * Slot con 1 tipo de parametro
 */
template <typename _t1>
class Slot1 : public VirtualSlot
{
public:
    Slot1(SEL selector) : VirtualSlot(selector) { };

    void call(QObject *sender, void **arguments)
    {
        cast_ptr(_t1, t, arguments[1]);
        this->imp(this->target, this->sel, t);
    };
};

/**
 * Slot con 2 tipos de parámetros
 */
template <typename _t1, typename _t2>
class Slot2 : public VirtualSlot
{
public:
    Slot2(SEL selector) : VirtualSlot(selector) {};

    void call(QObject *sender, void **arguments)
    {
        cast_ptr(_t1, first, arguments[1]);
        cast_ptr(_t2, second, arguments[2]);
        this->imp(this->target, this->sel, first, second);
    }
};

#endif  /* _SLOT1_H */
